/*
 * Copyright (c) 2015, Freescale Semiconductor, Inc.
 * Copyright 2016 NXP
 * All rights reserved.
 *
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#ifndef _EMBEDDED_RPC__CLIENT_TCP_TRANSPORT_H_
#define _EMBEDDED_RPC__CLIENT_TCP_TRANSPORT_H_

#include "erpc_framed_transport.h"
#include "erpc_threading.h"
#if defined(_MSC_VER) || defined(__MINGW32__)
#define WINSOCK_USED
#define _SOCK_TYPE_ SOCKET
#include <WinSock2.h>
#elif defined(__unix)
#define _SOCK_TYPE_ int
#endif

/*!
 * @addtogroup tcp_transport
 * @{
 * @file
 */

////////////////////////////////////////////////////////////////////////////////
// Classes
////////////////////////////////////////////////////////////////////////////////

namespace erpc {
/*!
 * @brief Client side of TCP/IP transport.
 *
 * @ingroup tcp_transport
 */
class ClientTCPTransport : public FramedTransport
{
public:
    /*!
     * @brief Constructor.
     *
     * This function initializes object attributes.
     *
     */
    ClientTCPTransport();

    /*!
     * @brief Constructor.
     *
     * This function initializes object attributes.
     *
     * @param[in] host Specify the host name or IP address of the computer.
     * @param[in] port Specify the listening port number.
     */
    ClientTCPTransport(const char *host, uint16_t port);

    /*!
     * @brief ClientTCPTransport destructor
     */
    virtual ~ClientTCPTransport(void);

    /*!
     * @brief This function set host and port of this transport layer.
     *
     * @param[in] host Specify the host name or IP address of the computer.
     * @param[in] port Specify the listening port number.
     */
    void configure(const char *host, uint16_t port);
    /*!
	 * @brief This function set host and port of this transport layer.
	 *
	 * @param[in] connTimeoutMills Specify timeout(milliseconds) for connecting. ignore if less than or equal to zero
	 * @param[in] sendTimeoutMills Specify timeout(milliseconds) for sending. ignore if less than or equal to zero
	 * @param[in] recvTimeoutMills Specify timeout(milliseconds) for receiving. ignore if less than or equal to zero
	 */
	void timeout(uint32_t connTimeoutMills,uint32_t sendTimeoutMills,uint32_t recvTimeoutMills);
    /*!
     * @brief This function will create host on server side, or connect client to the server.
     *
     * @retval #kErpcStatus_Success When creating host was successful or client connected successfully.
     * @retval #kErpcStatus_UnknownName Host name resolution failed.
     * @retval #kErpcStatus_ConnectionFailure Connecting to the specified host failed.
     */
    virtual erpc_status_t open(void);

    /*!
     * @brief This function disconnects client or stop server host.
     *
     * @retval #kErpcStatus_Success Always return this.
     */
    virtual erpc_status_t close(void);
	static const uint32_t DEFAULT_TIMEOUT_MILLS;

protected:
    const char *m_host;    /*!< Specify the host name or IP address of the computer. */
    uint16_t m_port;       /*!< Specify the listening port number. */
    static thread_local _SOCK_TYPE_ m_socket;          /*!< Socket number. */
    uint32_t m_connTimeoutMills;/*!< connect timeout(milliseconds). default 4 seconds */
    uint32_t m_sendTimeoutMills;/*!< send timeout(milliseconds). default 4 seconds */
    uint32_t m_recvTimeoutMills;/*!< receive timeout(milliseconds). default 4 seconds */

    /*!
     * @brief This function read data.
     *
     * @param[inout] data Preallocated buffer for receiving data.
     * @param[in] size Size of data to read.
     *
     * @retval #kErpcStatus_Success When data was read successfully.
     * @retval #kErpcStatus_ReceiveFailed When reading data ends with error.
     * @retval #kErpcStatus_ConnectionClosed Peer closed the connection.
     */
    virtual erpc_status_t underlyingReceive(uint8_t *data, uint32_t size);

    /*!
     * @brief This function writes data.
     *
     * @param[in] data Buffer to send.
     * @param[in] size Size of data to send.
     *
     * @retval #kErpcStatus_Success When data was written successfully.
     * @retval #kErpcStatus_SendFailed When writing data ends with error.
     * @retval #kErpcStatus_ConnectionClosed Peer closed the connection.
     */
    virtual erpc_status_t underlyingSend(const uint8_t *data, uint32_t size);

};

} // namespace erpc

/*! @} */

#endif // _EMBEDDED_RPC__CLIENT_TCP_TRANSPORT_H_
